package com.liyao.windowtest4.controller;

import com.liyao.windowtest4.Utils.GlobalConfig;
import com.liyao.windowtest4.Utils.SendWorkTasksUtils;
import com.liyao.windowtest4.Utils.SocketClientUtil;
import com.liyao.windowtest4.pojo.DataRow;
import com.liyao.windowtest4.pojo.Routine;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.FileWriter;

/**
 * @program: windowtest4
 * @description:
 * @author: liu yan
 * @create: 2024-10-29 13:02
 */
public class issueRoutineController implements Initializable {
    @FXML
    public ChoiceBox<String> torqueItems;
    public ChoiceBox<String> LoopItems;

    private Service<Void> service; // 类成员变量

    private SocketClientUtil clientUtil;
    private String RoutineId;

    private Routine Routine;

    private mainController mc;

    private SendWorkTasksUtils swtu;

    private WrenchTask wrenchTask;

    private List<JSONObject> myNet=new ArrayList<>();

    private String configDirPath = System.getProperty("user.dir") + File.separator + "config" + File.separator;




    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        // 从文件中读取数据并设置到ChoiceBox中
        List<String> items = readItemsFromFile();
        ObservableList<String> observableItems = FXCollections.observableArrayList(items);
        torqueItems.setItems(observableItems);

        ObservableList<String> options = FXCollections.observableArrayList(
                "循环", "单次"
        );
        LoopItems.setItems(options);

        // 如果需要，还可以设置默认值
        LoopItems.setValue("循环");
    }

    private List<String> readItemsFromFile() {
        List<String> items = new ArrayList<>();
        try {
            InputStream inputStream = new FileInputStream(configDirPath+"torqueItems.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = br.readLine()) != null) {
                JSONObject js=JSONObject.fromObject(line);
                items.add(js.getString("TorqueName")+","+js.getString("SN"));
                this.myNet.add(js);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return items;
    }

        public void issueEvent(ActionEvent actionEvent) {
            System.out.println("下发");
            String selectedTorque = torqueItems.getSelectionModel().getSelectedItem();
            String selectedLoop = LoopItems.getSelectionModel().getSelectedItem();

            if (selectedTorque == null || selectedTorque.isEmpty()) {
                showAlert("错误", "请选择一个扭矩选项！", Alert.AlertType.ERROR);
                return;
            }
            if (selectedLoop == null || selectedLoop.isEmpty()) {
                showAlert("错误", "请选择一个循环模式！", Alert.AlertType.ERROR);
                return;
            }

            String SN = selectedTorque.split(",")[1];
            String TorqueName = selectedTorque.split(",")[0];
            this.wrenchTask= GlobalConfig.getWrenchTask(SN);
            System.out.println("SN:"+SN+",Name:"+TorqueName);

            this.service = new Service<>() {
                // 添加一个取消标志
                private volatile boolean cancelled = false;
                @Override
                protected Task<Void> createTask() {
                    return new Task<Void>() {
                        @Override
                        protected Void call() throws Exception {
                            try {
                                InputStream inputStream= new FileInputStream(configDirPath+"torqueItems.txt");
                                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                                String line;
                                while ((line = br.readLine()) != null) {
                                    if (line.contains("\"SN\":\"" + SN + "\"")) {
                                        wrenchTask.stop();
                                        WrenchTask wt=null;
                                        JSONObject js = JSONObject.fromObject(line);
                                        JSONObject json=new JSONObject();
                                        json.put("SN",js.getString("SN"));
                                        json.put("RoutineId",RoutineId);
                                        json.put("pattern",selectedLoop);
                                        if(selectedLoop.equals("循环")){
                                            //写入文档中
                                            writeTxt(js.getString("SN"),json.toString());

                                            for (JSONObject jsona:myNet) {
                                                if(jsona.getString("SN").equals(SN)){
                                                    wt=new WrenchTask();
                                                    wt.WrenchTaskInit(jsona.getString("TorqueName"), jsona.getString("Host"), jsona.getInt("Port"),mc);
                                                    wt.start(SN);
                                                    GlobalConfig.setWrenchTask(SN,wt);
                                                    break;
                                                }
                                            }
                                            System.out.println("又启动了:::"+wt.isReturnState());
                                            updateMessage("正在下发任务，连接扳手中...");
                                            Thread.sleep(2000);
                                            if(wt.isReturnState()){
                                                //连接成功
                                                updateMessage("下发成功");
                                                cancelled=true;
                                                break;
                                            }else{
                                                updateMessage("下发过程未连接到扳手，可关闭此窗口等待扳手连接即可");
                                                // 模拟延迟
                                                Thread.sleep(1000);
                                            }
                                        }else{
                                            System.out.println("任务是单次的，模拟执行完毕，即将重启socket");
                                            //调用单次循环的方法
                                            updateMessage("正在连接扳手，请确保扳手在线，请勿关闭此窗口<br>连接扳手中...");
                                            //连接扳手的操作
                                            String serverAddress="";
                                            int serverPort=0;
                                            String serverWrenchName="";

                                            for (JSONObject jsona:myNet) {
                                                if(jsona.getString("SN").equals(SN)){
                                                    serverAddress=jsona.getString("Host");
                                                    serverPort=jsona.getInt("Port");
                                                    serverWrenchName= jsona.getString("TorqueName");
                                                    break;
                                                }
                                            }
                                            int maxRetries = 5;
                                            int retryCount = 0;
                                            while (!cancelled && retryCount < maxRetries) {
                                                System.out.println(":执行连接，IP地址："+serverAddress+",端口号："+serverPort);
                                                System.out.println("正在第" + (retryCount + 1) + "次连接扳手，请勿关闭此窗口");
                                                updateMessage("正在第" + (retryCount + 1) + "次连接扳手，请勿关闭此窗口");
                                                //InetSocketAddress socketAddress = new InetSocketAddress(serverAddress, serverPort);
                                                //Socket socket = new Socket();
                                                try {
                                                    SocketClientUtil scu=new SocketClientUtil(serverAddress,serverPort);
                                                    scu.connect();
                                                    updateMessage("扳手连接成功,可关闭此窗口");
                                                    scu.sendMessage("RSVI;01;"+SN+";01;\r\n");
                                                    cancelled=true;
                                                    String resp0=scu.receiveMessage();
                                                    System.out.println("resp0"+resp0);
                                                    String wrenchSpan=Double.parseDouble(resp0.split(";")[8])/10+"";
                                                    JSONArray jarr=new JSONArray();
                                                    String routineName="";

                                                    //获取程序
                                                    try {
                                                        InputStream inputStream1=getClass().getClassLoader().getResourceAsStream("Routine.txt");
                                                        if(inputStream1==null){
                                                            System.err.println("无法找到系统文件：Routine.txt");
                                                        }
                                                        BufferedReader br2 = new BufferedReader(new InputStreamReader(inputStream1));
                                                        String line2;
                                                        while ((line2 = br2.readLine()) != null) {
                                                            if (line2.contains("\"code\":\"" + RoutineId + "\"")) {
                                                                JSONObject j=JSONObject.fromObject(line2);
                                                                routineName=j.getString("RoutineName");
                                                                jarr=JSONArray.fromObject(j.getString("content"));
                                                                System.out.println(jarr);
                                                                break;
                                                            }
                                                        }
                                                    }catch (IOException e){
                                                        updateMessage("拧紧程序文件读取失败");
                                                    }

                                                    int i=0;
                                                    System.out.println("jarr的长度"+jarr.size());
                                                    while(i<jarr.size()){
                                                        System.out.println("单次进入到循环内");
                                                        scu.close();
                                                        scu.connect();
                                                        JSONObject jjs=JSONObject.fromObject(jarr.get(i));
                                                        scu.sendMessage("RSSP;02;"+SN+";01;1;"+routineName+";0;2;"+wrenchSpan+";"+jjs.getString("TorqueMin")+";"+jjs.getString("TorqueTarget")+";"+jjs.getString("TorqueMax")+";"+jjs.getString("StartAngle")+";"+jjs.getString("AngleMin")+";"+jjs.getString("AngleTarget")+";"+jjs.getString("AngleMax")+";1;1;0;1;0;0;\r\n");
                                                        String resp1=scu.receiveMessage();
                                                        System.out.println("单次resp1:"+resp1);
                                                        if (resp1 != null) {
                                                            if(resp1.split(";")[4].equals("0")){
                                                                System.out.println("单次下发程序成功："+routineName);
                                                                //下发成功
                                                                scu.close();
                                                                boolean a=true;
                                                                while (a){
                                                                    String resp2 = null;
                                                                    scu.connect();
                                                                    scu.sendMessage("RSTS;1;"+SN+";1;\r\n");
                                                                    // 从服务器接收消息
                                                                    resp2 = scu.receiveMessage();

                                                                    System.out.println("Server response2: " + resp2);
                                                                    if(resp2!=null && resp2.split(";")[7].equals("1")){
                                                                        System.out.println("有数据要上传了");
                                                                        scu.close();
                                                                        scu.connect();
                                                                        scu.sendMessage("RSTD;01;"+SN+";01;\r\n");
                                                                        // 从服务器接收消息
                                                                        String resp3 = null;
                                                                        resp3 = scu.receiveMessage();
                                                                        System.out.println("单次resp3: " + resp3);
                                                                        if(resp3!=null){
                                                                            System.out.println("ww333:"+resp3.split(";")[2]+","+resp3.split(";")[11]+","+resp3.split(";")[12]);
                                                                            System.out.println("ww334:"+SN+","+resp3.split(";")[11]+","+routineName);
                                                                            if(resp3.split(";")[2].equals(SN) && resp3.split(";")[11].equals("1") && resp3.split(";")[12].equals(routineName)){
                                                                                //判断扭矩是否合格，不合格重新发送的逻辑
                                                                                System.out.println("ww:"+resp3.split(";")[2]+","+resp3.split(";")[11]+","+resp3.split(";")[12]);

                                                                                //写入data中
                                                                                WriteTxt(serverWrenchName,resp3.split(";")[22]);

                                                                                a=false;//跳出循环
                                                                                System.out.println("跳出循环");

                                                                            }else{
                                                                                a=true;
                                                                                System.out.println("继续循环");
                                                                            }
                                                                        }
                                                                        scu.close();
                                                                    }else{
                                                                        System.out.println("没有数据要上传的");
                                                                        scu.close();
                                                                        a=true;
                                                                        Thread.sleep(3000);
                                                                    }
                                                                }
                                                                i++;
                                                            }else if(resp1.split(";")[4].equals("6")){
                                                                System.out.println("扳手正忙");
                                                                scu.close();
                                                                scu.connect();
                                                                scu.sendMessage("RSTD;01;"+SN+";01;\r\n");
                                                                // 从服务器接收消息
                                                                String resp3 = null;
                                                                try {
                                                                    resp3 = scu.receiveMessage();
                                                                } catch (IOException e) {
                                                                    throw new RuntimeException(e);
                                                                }
                                                                System.out.println("Server response3-1: " + resp3);

                                                                //验证PsetID鱼PsetName是否对应，如果不对应不跳出循环，接着询问
                                                                if(resp3.split(";")[2].equals(SN) && resp3.split(";")[11].equals("1") && resp3.split(";")[12].equals(routineName)){
                                                                    //判断扭矩是否合格，不合格重新发送的逻辑
                                                                    System.out.println(resp3.split(";")[2]+","+resp3.split(";")[11]+","+resp3.split(";")[12]);
                                                                    //写入data中
                                                                    try {
                                                                        WriteTxt(SN,resp3.split(";")[22]);
                                                                    } catch (IOException e) {
                                                                        throw new RuntimeException(e);
                                                                    }
                                                                    //a=false;//跳出循环
                                                                    //System.out.println("跳出循环");
                                                                }else{
                                                                    //a=true;
                                                                    System.out.println("继续循环(正忙)");
                                                                    System.out.println(resp3.split(";")[2]+","+resp3.split(";")[11]+","+resp3.split(";")[12]);
                                                                }
                                                            }else if(resp1.split(";")[4].equals("2")){
                                                                System.out.println("无效的扭矩参数");
                                                            }
                                                        }
                                                    }
                                                    updateMessage("任务执行完毕");
                                                    wt=new WrenchTask();
                                                    wt.WrenchTaskInit(serverWrenchName, serverAddress, serverPort,mc);
                                                    wt.start(SN);
                                                    GlobalConfig.setWrenchTask(SN,wt);
                                                } catch (IOException e) {
                                                    retryCount++;
                                                    System.out.println("单次任务下发的异常："+e);
                                                    Thread.sleep(3000);
                                                }
                                                if(retryCount==5){
                                                    updateMessage("扳手连接失败，请检查扳手网络");
                                                    wt=new WrenchTask();
                                                    wt.WrenchTaskInit(serverWrenchName, serverAddress, serverPort,mc);
                                                    wt.start(SN);
                                                    GlobalConfig.setWrenchTask(SN,wt);
                                                }
                                            }
                                        }
                                        if (isCancelled()) {
                                            updateMessage("任务已取消");
                                        }
                                        break;
                                    }
                                }
                            } catch (IOException e) {
                                updateMessage("读取文件失败: " + e.getMessage());
                            }
                            return null;
                        }
                        @Override
                        protected void cancelled() {
                            super.cancelled();
                            // 当任务被取消时，设置取消标志（这通常会在调用service.cancel()时自动发生）
                            cancelled = true;
                            // 您可能还需要在这里添加额外的清理逻辑，比如关闭已经打开的Socket等
                        }
                    };
                }
            };
            Dialog<Void> dialog = createDialog("正在下发任务...");
    //        service.setOnSucceeded(event -> dialog.close());
            service.setOnSucceeded(event -> {
                PauseTransition delay = new PauseTransition(Duration.seconds(3)); // 延迟3秒
                delay.setOnFinished(event2 -> dialog.close()); // 延迟结束后关闭对话框
                delay.play();
            });
            // 在对话框关闭时取消服务
            dialog.setOnCloseRequest(event -> {
    //            if (service.isRunning()) {
    //                service.cancel();
    ////                try {
//                try {
//                    swtu.closeSocket();
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
    ////                } catch (IOException e) {
    ////                    throw new RuntimeException(e);
    ////                }
    //            }
                dialog.close(); // 这行通常不需要，因为对话框已经在关闭请求中了
            });

            service.start();

            dialog.showAndWait();
            Stage stage = (Stage) ((Button) actionEvent.getSource()).getScene().getWindow();
            stage.close();
        }

    private Dialog<Void> createDialog(String title) {
        Dialog<Void> dialog = new Dialog<>();
        dialog.setTitle(title);
        dialog.setHeaderText(null);
        dialog.setGraphic(null);

        // 创建一个带有首选尺寸的Label
        Label label = new Label();
        label.setPrefWidth(400); // 设置首选宽度，可以根据需要调整
        label.setWrapText(true); // 启用文本换行
        dialog.getDialogPane().setContent(label);

        dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CLOSE);

        // 更新标签内容
        service.messageProperty().addListener((obs, oldMessage, newMessage) -> {
            Platform.runLater(() -> label.setText(newMessage));
        });

        // 尝试调整对话框的初始尺寸（这不是标准方法，但可能有助于在某些情况下改善显示效果）
        // 注意：这种方法的效果可能因JavaFX版本和平台而异
        dialog.getDialogPane().prefWidthProperty().bind(label.prefWidthProperty());
        dialog.getDialogPane().prefHeightProperty().bind(label.prefHeightProperty().add(50)); // 额外的高度用于按钮等


        return dialog;
    }

    // 显示弹窗提醒的方法
    private void showAlert(String title, String content, Alert.AlertType alertType) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setContentText(content);
        alert.setHeaderText(null);
        alert.initOwner(torqueItems.getScene().getWindow()); // 确保弹窗在当前窗口上
        alert.showAndWait();
    }

//    private void writeTxt(String SN,String data) throws IOException {
//        //"src/main/resources/taskItems.txt"
//        String filePath = "taskItems.txt";
//        System.out.println("data:"+data);
//        // 定义要写入的文件路径
//        String tempFilePath = filePath + ".tmp";
//        String targetCode = SN;
//
//        // 读取文件内容到列表中
////        List<String> lines = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8);
//        // 通过类加载器获取文件的输入流并读取文件内容到列表中
//        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filePath);
//        if (inputStream == null) {
//            System.err.println("无法找到资源文件: " + filePath);
////            return;
//        }
//        List<String> lines = new ArrayList<>();
//        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
//            String line;
//            while ((line = reader.readLine())!= null) {
//                lines.add(line);
//            }
//        }
//
//
//        // 查找并删除目标行
//        Iterator<String> iterator = lines.iterator();
//        boolean deleted = false;
//        while (iterator.hasNext()) {
//            String line = iterator.next();
//            if (line.contains("\"SN\":\"" + targetCode + "\"")) {
//                iterator.remove();
//                deleted = true;
////                break; // 如果只需要删除第一处匹配，就跳出循环
//            }
//        }
//
//        if (!deleted) {
//            System.out.println("未找到code为" + targetCode + "的行。");
//            //return;
//        }
//
//        // 将新行添加到列表中（这里添加到末尾，你也可以选择添加到删除行的位置）
//        System.out.println("添加的结果："+lines.add(data));
//        System.out.println("添加的结果串："+lines);
//
//        // 将修改后的内容写回临时文件
//        try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFilePath))) {
//            for (String line : lines) {
//                writer.write(line);
//                writer.newLine();
//            }
//        } catch (IOException e) {
//            System.err.println("你好"+e);
//            e.printStackTrace();
//            return;
//        }
//
//        // 替换原始文件
//        URL url = getClass().getClassLoader().getResource("taskItems.txt");
//        String getPath=url.getPath();
//        if (getPath.startsWith("/")) {
//            getPath = getPath.substring(1);
//        }
//        //苹果系统要去掉 file:
////        if(getPath.contains("file:")){
////            getPath= getPath.replace("file:","");
////        }
//        // windows要去掉file:/
////        if(getPath.contains("file:/")){
////            getPath= getPath.replace("file:/","");
////        }
////        if(getPath.contains("jar:")){
////            getPath= getPath.replace("jar:","");
////        }
//        System.out.println(getPath);
//        System.out.println(url.toString());
//        System.out.println(url.getPath());
//        try {
//            Files.deleteIfExists(Paths.get(getPath));
//            Files.move(Paths.get(tempFilePath), Paths.get(getPath), StandardCopyOption.REPLACE_EXISTING);
//            System.out.println("文件修改成功！");
//        } catch (IOException e) {
//            System.out.println("nihao "+e);
//            e.printStackTrace();
//        }
//    }

    private void writeTxt(String SN,String data) throws IOException, URISyntaxException {
        String filePath = configDirPath+"taskItems.txt";
        String targetSN = SN;
        try {
            // 读取文件内容到列表中
            List<String> lines = readFileLines(filePath);

            // 查找并删除目标行
            lines = deleteTargetLine(lines, targetSN);

            // 将新数据添加到列表
            lines.add(data);

            // 将修改后的内容写回文件
            writeLinesToFile(lines, filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static List<String> readFileLines(String filePath) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine())!= null) {
                lines.add(line);
            }
        }
        return lines;
    }

    private static List<String> deleteTargetLine(List<String> lines, String targetSN) {
        List<String> newLines = new ArrayList<>();
        for (String line : lines) {
            if (!line.contains("\"SN\":\"" + targetSN + "\"")) {
                newLines.add(line);
            } else {
                System.out.println("删除结束");
            }
        }
        return newLines;

    }

    private static void writeLinesToFile(List<String> lines, String filePath) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
//        try (FileOutputStream fos=new FileOutputStream(filePath,true);
//             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos,"UTF-8"))) {
            for (String line : lines) {
                writer.write(line);
                writer.newLine();
            }
        }catch (Exception e){
            System.out.println("created taskItems Lose");
        }
    }

    public void setDataItem(Routine currentRowItem,mainController mc) {
        this.RoutineId=currentRowItem.getID();
        this.Routine=currentRowItem;
        this.mc=mc;
    }

    private void WriteTxt(String wrenchName,String torqueValue) throws IOException {
        System.out.println("单次到写入的方法了");
        JSONArray arr=new JSONArray();
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("data.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = br.readLine()) != null) {
                arr.add(JSONObject.fromObject(line));
            }
        } catch (IOException e) {
            System.err.println("读取data.txt失败");
            e.printStackTrace();
        }
        SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd");

        int totality=0;
        for (int i = 0; i < arr.size(); i++) {
            JSONObject js=JSONObject.fromObject(arr.get(i));
            if(js.getString("timestamp").contains(sdf1.format(new Date()))){
                totality++;
            }
        }
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String number="CG"+(arr.size()+1);
        DataRow newData = new DataRow(number, wrenchName, torqueValue+" N.m", sdf.format(new Date()), totality);

        Platform.runLater(() -> mc.addDataEvent(newData));

        URL url = getClass().getClassLoader().getResource("data.txt");
        if (url == null) {
            throw new IOException("无法找到data.txt文件");
        }
        // 将URL转换为文件路径格式（不同操作系统可能需要不同处理）
        String filePath = url.getPath();
        // 将数据（包括新添加的数据）写入文件
        try (FileOutputStream fos = new FileOutputStream(filePath,true);
             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))) { // true 表示追加模式
            // 遍历数据列表并写入文件
            writer.write(newData.toString()); // 假设DataRow有一个合适的toString()方法，该方法返回包含所有字段的字符串表示
            writer.newLine(); // 每行数据后换行
            System.out.println("单次写入文件成功");
        } catch (IOException e) {
            e.printStackTrace(); // 打印错误堆栈信息到控制台（通常不推荐在生产环境中这样做）
            // 在实际应用中，您应该使用更用户友好的错误处理方式，比如显示一个错误消息对话框
        }
        //写入数据库
        System.out.println("是否需要写入数据库 :"+mc.getDbstate());
        if(mc.getDbstate().equals("true")){
            try{
                mc.service.insertDB(newData,mc.getDbTable());
            }catch (Exception e){
                System.err.println("数据库错误："+e);
            }
        }else{
            System.out.println("不用写入数据库。。。");
        }
    }
}
